From 95e3daef91007406752b83163c5784df434ce175 Mon Sep 17 00:00:00 2001 From: Mike Baker Date: Sat, 4 Nov 2006 01:45:26 +0000 Subject: [PATCH] more diag cleanup SVN-Revision: 5434 --- openwrt/target/linux/package/diag/src/diag.c | 548 +++++++------------ openwrt/target/linux/package/diag/src/diag.h | 165 ++++++ 2 files changed, 377 insertions(+), 336 deletions(-) create mode 100644 openwrt/target/linux/package/diag/src/diag.h diff --git a/openwrt/target/linux/package/diag/src/diag.c b/openwrt/target/linux/package/diag/src/diag.c index 149dc91ac6..5f460f59d9 100644 --- a/openwrt/target/linux/package/diag/src/diag.c +++ b/openwrt/target/linux/package/diag/src/diag.c @@ -35,66 +35,11 @@ #include #include -#define MODULE_NAME "diag" - -#define MAX_GPIO 8 -#define FLASH_TIME HZ/6 - -#define EXTIF_ADDR 0x1f000000 -#define EXTIF_UART (EXTIF_ADDR + 0x00800000) - -/* For LEDs */ -#define GPIO_TYPE_NORMAL (0x0 << 24) -#define GPIO_TYPE_EXTIF (0x1 << 24) -#define GPIO_TYPE_MASK (0xf << 24) +#include "diag.h" static unsigned int gpiomask = 0; module_param(gpiomask, int, 0644); -enum polarity_t { - REVERSE = 0, - NORMAL = 1, -}; - -enum { - PROC_BUTTON, - PROC_LED, - PROC_MODEL, - PROC_GPIOMASK -}; - -struct prochandler_t { - int type; - void *ptr; -}; - -struct button_t { - struct prochandler_t proc; - char *name; - u32 gpio; - unsigned long seen; - u8 pressed; -}; - -struct led_t { - struct prochandler_t proc; - char *name; - u32 gpio; - u8 polarity; - u8 flash; - u8 state; -}; - -struct platform_t { - char *name; - - struct button_t buttons[MAX_GPIO]; - u32 button_mask; - u32 button_polarity; - - struct led_t leds[MAX_GPIO]; -}; - enum { /* Linksys */ WAP54GV1, @@ -439,34 +384,11 @@ static struct platform_t __init platforms[] = { }, }; -static struct proc_dir_entry *diag, *leds; - -extern void *bcm947xx_sbh; -#define sbh bcm947xx_sbh -extern spinlock_t bcm947xx_sbh_lock; -#define sbh_lock bcm947xx_sbh_lock - -static int sb_irq(void *sbh); -static struct platform_t platform; - -extern char *nvram_get(char *str); - -static void led_flash(unsigned long dummy); - static inline char __init *getvar(char *str) { return nvram_get(str)?:""; } -static void set_led_extif(struct led_t *led) -{ - volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK); - if (led->state) - *addr = 0xFF; - else - *addr; -} - static struct platform_t __init *platform_detect(void) { char *boardnum, *boardtype, *buf; @@ -559,161 +481,23 @@ static struct platform_t __init *platform_detect(void) return NULL; } -static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos); -static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data); -static struct file_operations diag_proc_fops = { - read: diag_proc_read, - write: diag_proc_write -}; - - - -static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ -#ifdef LINUX_2_4 - struct inode *inode = file->f_dentry->d_inode; - struct proc_dir_entry *dent = inode->u.generic_ip; -#else - struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode); -#endif - char *page; - int len = 0; - - if ((page = kmalloc(1024, GFP_KERNEL)) == NULL) - return -ENOBUFS; - - if (dent->data != NULL) { - struct prochandler_t *handler = (struct prochandler_t *) dent->data; - switch (handler->type) { - case PROC_LED: { - struct led_t * led = (struct led_t *) handler->ptr; - if (led->flash) { - len = sprintf(page, "f\n"); - } else { - if (led->gpio & GPIO_TYPE_EXTIF) { - len = sprintf(page, "%d\n", led->state); - } else { - u32 in = (sb_gpioin(sbh) & led->gpio ? 1 : 0); - u8 p = (led->polarity == NORMAL ? 0 : 1); - len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0)); - } - } - break; - } - case PROC_MODEL: - len = sprintf(page, "%s\n", platform.name); - break; - case PROC_GPIOMASK: - len = sprintf(page, "%d\n", gpiomask); - break; - } - } - len += 1; - - if (*ppos < len) { - len = min_t(int, len - *ppos, count); - if (copy_to_user(buf, (page + *ppos), len)) { - kfree(page); - return -EFAULT; - } - *ppos += len; - } else { - len = 0; - } - - return len; -} - - -static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data) -{ -#ifdef LINUX_2_4 - struct inode *inode = file->f_dentry->d_inode; - struct proc_dir_entry *dent = inode->u.generic_ip; -#else - struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode); -#endif - char *page; - int ret = -EINVAL; - - if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL) - return -ENOBUFS; - - if (copy_from_user(page, buf, count)) { - kfree(page); - return -EINVAL; - } - page[count] = 0; - - if (dent->data != NULL) { - struct prochandler_t *handler = (struct prochandler_t *) dent->data; - switch (handler->type) { - case PROC_LED: { - struct led_t *led = (struct led_t *) handler->ptr; - int p = (led->polarity == NORMAL ? 0 : 1); - - if (!(led->gpio & GPIO_TYPE_EXTIF) && (led->gpio & gpiomask)) - break; - - if (page[0] == 'f') { - led->flash = 1; - led_flash(0); - } else { - led->flash = 0; - if (led->gpio & GPIO_TYPE_EXTIF) { - led->state = p ^ ((page[0] == '1') ? 1 : 0); - set_led_extif(led); - } else { - sb_gpioouten(sbh, led->gpio, led->gpio); - sb_gpiocontrol(sbh, led->gpio, 0); - sb_gpioout(sbh, led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0)); - } - } - break; - } - case PROC_GPIOMASK: { - u32 mask; - gpiomask = simple_strtoul(page, NULL, 16); - - mask = platform.button_mask & ~gpiomask; - - sb_gpioouten(sbh, mask, 0); - sb_gpiocontrol(sbh, mask, 0); - platform.button_polarity = sb_gpioin(sbh) & mask; - sb_gpiointpolarity(sbh, mask, platform.button_polarity); - sb_gpiointmask(sbh, mask, mask); - - break; - } - } - ret = count; - } - - kfree(page); - return ret; -} - -struct event_t { - struct tq_struct tq; - char buf[256]; - char *argv[3]; - char *envp[6]; -}; - -static void hotplug_button(struct event_t *event) -{ - call_usermodehelper (event->argv[0], event->argv, event->envp); - kfree(event); -} - static void set_irqenable(int enabled) { unsigned int coreidx; unsigned long flags; chipcregs_t *cc; + int irq; spin_lock_irqsave(sbh_lock, flags); coreidx = sb_coreidx(sbh); + + + irq = sb_irq(sbh) + 2; + if (enabled) + request_irq(irq, button_handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", button_handler); + else + free_irq(irq, button_handler); + if ((cc = sb_setcore(sbh, SB_CC, 0))) { int intmask; @@ -728,6 +512,36 @@ static void set_irqenable(int enabled) spin_unlock_irqrestore(sbh_lock, flags); } +static void register_buttons(struct button_t *b) +{ + for (; b->name; b++) + platform.button_mask |= b->gpio; + + platform.button_mask &= ~gpiomask; + + sb_gpioouten(sbh, platform.button_mask, 0); + sb_gpiocontrol(sbh, platform.button_mask, 0); + platform.button_polarity = sb_gpioin(sbh) & platform.button_mask; + sb_gpiointpolarity(sbh, platform.button_mask, platform.button_polarity); + sb_gpiointmask(sbh, platform.button_mask, platform.button_mask); + + set_irqenable(1); +} + +static void unregister_buttons(struct button_t *b) +{ + + sb_gpiointmask(sbh, platform.button_mask, 0); + + set_irqenable(0); +} + +static void hotplug_button(struct event_t *event) +{ + call_usermodehelper (event->argv[0], event->argv, event->envp); + kfree(event); +} + static void button_handler(int irq, void *dev_id, struct pt_regs *regs) { @@ -739,7 +553,6 @@ static void button_handler(int irq, void *dev_id, struct pt_regs *regs) changed = platform.button_polarity ^ in; platform.button_polarity = in; - set_irqenable(0); for (b = platform.buttons; b->name; b++) { struct event_t *event; @@ -773,12 +586,59 @@ static void button_handler(int irq, void *dev_id, struct pt_regs *regs) b->seen = jiffies; } - set_irqenable(1); } -static struct timer_list led_timer = { - function: &led_flash -}; +static void register_leds(struct led_t *l) +{ + struct proc_dir_entry *p; + u32 mask; + u32 val; + + leds = proc_mkdir("led", diag); + if (!leds) + return; + + for(; l->name; l++) { + if (l->gpio & gpiomask) + continue; + + if (l->gpio & GPIO_TYPE_EXTIF) { + l->state = 0; + set_led_extif(l); + } else { + mask |= l->gpio; + val |= (l->polarity == NORMAL)?0:l->gpio; + } + + if ((p = create_proc_entry(l->name, S_IRUSR, leds))) { + l->proc.type = PROC_LED; + l->proc.ptr = l; + p->data = (void *) &l->proc; + p->proc_fops = &diag_proc_fops; + } + } + + sb_gpioouten(sbh, mask, mask); + sb_gpiocontrol(sbh, mask, 0); + sb_gpioout(sbh, mask, val); +} + +static void unregister_leds(struct led_t *l) +{ + for(; l->name; l++) + remove_proc_entry(l->name, leds); + + remove_proc_entry("led", diag); +} + +static void set_led_extif(struct led_t *led) +{ + volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK); + if (led->state) + *addr = 0xFF; + else + *addr; +} static void led_flash(unsigned long dummy) { struct led_t *l; @@ -810,92 +670,126 @@ static void led_flash(unsigned long dummy) { } } -static void __init register_buttons(struct button_t *b) -{ - int irq = sb_irq(sbh) + 2; - u32 mask; - - request_irq(irq, button_handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", button_handler); - - for (; b->name; b++) - platform.button_mask |= b->gpio; - - mask = platform.button_mask & ~gpiomask; - - sb_gpioouten(sbh, mask, 0); - sb_gpiocontrol(sbh, mask, 0); - platform.button_polarity = sb_gpioin(sbh) & mask; - sb_gpiointpolarity(sbh, mask, platform.button_polarity); - sb_gpiointmask(sbh, mask, mask); - - set_irqenable(1); -} - -static void __exit unregister_buttons(struct button_t *b) -{ - int irq = sb_irq(sbh) + 2; - - sb_gpiointmask(sbh, platform.button_mask, 0); - - free_irq(irq, button_handler); -} - -static void __init register_leds(struct led_t *l) +static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *p; - - leds = proc_mkdir("led", diag); - if (!leds) - return; - - for(; l->name; l++) { - if (l->gpio & gpiomask) - continue; +#ifdef LINUX_2_4 + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *dent = inode->u.generic_ip; +#else + struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode); +#endif + char *page; + int len = 0; - if (l->gpio & GPIO_TYPE_EXTIF) { - l->state = 0; - set_led_extif(l); - } else { - sb_gpioouten(sbh, l->gpio, l->gpio); - sb_gpiocontrol(sbh, l->gpio, 0); - sb_gpioout(sbh, l->gpio, (l->polarity == NORMAL)?0:l->gpio); + if ((page = kmalloc(1024, GFP_KERNEL)) == NULL) + return -ENOBUFS; + + if (dent->data != NULL) { + struct prochandler_t *handler = (struct prochandler_t *) dent->data; + switch (handler->type) { + case PROC_LED: { + struct led_t * led = (struct led_t *) handler->ptr; + if (led->flash) { + len = sprintf(page, "f\n"); + } else { + if (led->gpio & GPIO_TYPE_EXTIF) { + len = sprintf(page, "%d\n", led->state); + } else { + u32 in = (sb_gpioin(sbh) & led->gpio ? 1 : 0); + u8 p = (led->polarity == NORMAL ? 0 : 1); + len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0)); + } + } + break; + } + case PROC_MODEL: + len = sprintf(page, "%s\n", platform.name); + break; + case PROC_GPIOMASK: + len = sprintf(page, "%d\n", gpiomask); + break; } + } + len += 1; - if ((p = create_proc_entry(l->name, S_IRUSR, leds))) { - l->proc.type = PROC_LED; - l->proc.ptr = l; - p->data = (void *) &l->proc; - p->proc_fops = &diag_proc_fops; + if (*ppos < len) { + len = min_t(int, len - *ppos, count); + if (copy_to_user(buf, (page + *ppos), len)) { + kfree(page); + return -EFAULT; } + *ppos += len; + } else { + len = 0; } -} - -static void __exit unregister_leds(struct led_t *l) -{ - for(; l->name; l++) - remove_proc_entry(l->name, leds); - remove_proc_entry("led", diag); + return len; } -static void __exit diag_exit(void) + +static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data) { +#ifdef LINUX_2_4 + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *dent = inode->u.generic_ip; +#else + struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode); +#endif + char *page; + int ret = -EINVAL; - del_timer(&led_timer); + if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL) + return -ENOBUFS; - if (platform.buttons) - unregister_buttons(platform.buttons); + if (copy_from_user(page, buf, count)) { + kfree(page); + return -EINVAL; + } + page[count] = 0; + + if (dent->data != NULL) { + struct prochandler_t *handler = (struct prochandler_t *) dent->data; + switch (handler->type) { + case PROC_LED: { + struct led_t *led = (struct led_t *) handler->ptr; + int p = (led->polarity == NORMAL ? 0 : 1); + + if (page[0] == 'f') { + led->flash = 1; + led_flash(0); + } else { + led->flash = 0; + if (led->gpio & GPIO_TYPE_EXTIF) { + led->state = p ^ ((page[0] == '1') ? 1 : 0); + set_led_extif(led); + } else { + sb_gpioouten(sbh, led->gpio, led->gpio); + sb_gpiocontrol(sbh, led->gpio, 0); + sb_gpioout(sbh, led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0)); + } + } + break; + } + case PROC_GPIOMASK: + gpiomask = simple_strtoul(page, NULL, 16); - if (platform.leds) - unregister_leds(platform.leds); + if (platform.buttons) { + unregister_buttons(platform.buttons); + register_buttons(platform.buttons); + } - remove_proc_entry("model", diag); - remove_proc_entry("gpiomask", diag); - remove_proc_entry("diag", NULL); -} + if (platform.leds) { + unregister_leds(platform.leds); + register_leds(platform.leds); + } + break; + } + ret = count; + } -static struct prochandler_t proc_model = { .type = PROC_MODEL }; -static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK }; + kfree(page); + return ret; +} static int __init diag_init(void) { @@ -935,6 +829,22 @@ static int __init diag_init(void) return 0; } +static void __exit diag_exit(void) +{ + + del_timer(&led_timer); + + if (platform.buttons) + unregister_buttons(platform.buttons); + + if (platform.leds) + unregister_leds(platform.leds); + + remove_proc_entry("model", diag); + remove_proc_entry("gpiomask", diag); + remove_proc_entry("diag", NULL); +} + EXPORT_NO_SYMBOLS; module_init(diag_init); @@ -942,37 +852,3 @@ module_exit(diag_exit); MODULE_AUTHOR("Mike Baker, Felix Fietkau / OpenWrt.org"); MODULE_LICENSE("GPL"); - -/* TODO: export existing sb_irq instead */ -static int sb_irq(void *sbh) -{ - uint idx; - void *regs; - sbconfig_t *sb; - uint32 flag, sbipsflag; - uint irq = 0; - - regs = sb_coreregs(sbh); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); - flag = (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK); - - idx = sb_coreidx(sbh); - - if ((regs = sb_setcore(sbh, SB_MIPS, 0)) || - (regs = sb_setcore(sbh, SB_MIPS33, 0))) { - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); - - /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ - sbipsflag = R_REG(&sb->sbipsflag); - for (irq = 1; irq <= 4; irq++, sbipsflag >>= 8) { - if ((sbipsflag & 0x3f) == flag) - break; - } - if (irq == 5) - irq = 0; - } - - sb_setcoreidx(sbh, idx); - - return irq; -} diff --git a/openwrt/target/linux/package/diag/src/diag.h b/openwrt/target/linux/package/diag/src/diag.h new file mode 100644 index 0000000000..95c31e056f --- /dev/null +++ b/openwrt/target/linux/package/diag/src/diag.h @@ -0,0 +1,165 @@ +/* + * diag.h - GPIO interface driver for Broadcom boards + * + * Copyright (C) 2006 Mike Baker , + * Felix Fietkau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id:$ + */ + +#define MODULE_NAME "diag" + +#define MAX_GPIO 8 +#define FLASH_TIME HZ/6 + +enum polarity_t { + REVERSE = 0, + NORMAL = 1, +}; + +enum { + PROC_BUTTON, + PROC_LED, + PROC_MODEL, + PROC_GPIOMASK +}; + +struct prochandler_t { + int type; + void *ptr; +}; + +struct button_t { + struct prochandler_t proc; + char *name; + u32 gpio; + unsigned long seen; + u8 pressed; +}; + +struct led_t { + struct prochandler_t proc; + char *name; + u32 gpio; + u8 polarity; + u8 flash; + u8 state; +}; + +struct platform_t { + char *name; + + struct button_t buttons[MAX_GPIO]; + u32 button_mask; + u32 button_polarity; + + struct led_t leds[MAX_GPIO]; +}; + +struct event_t { + struct tq_struct tq; + char buf[256]; + char *argv[3]; + char *envp[6]; +}; + +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock + +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; +extern char *nvram_get(char *str); + +static struct platform_t platform; + +/* buttons */ + +static void set_irqenable(int enabled); + +static void register_buttons(struct button_t *b); +static void unregister_buttons(struct button_t *b); + +static void hotplug_button(struct event_t *event); +static void button_handler(int irq, void *dev_id, struct pt_regs *regs); + +/* leds */ + +static void register_leds(struct led_t *l); +static void unregister_leds(struct led_t *l); + +#define EXTIF_ADDR 0x1f000000 +#define EXTIF_UART (EXTIF_ADDR + 0x00800000) + +#define GPIO_TYPE_NORMAL (0x0 << 24) +#define GPIO_TYPE_EXTIF (0x1 << 24) +#define GPIO_TYPE_MASK (0xf << 24) + +static void set_led_extif(struct led_t *led); +static void led_flash(unsigned long dummy); + +static struct timer_list led_timer = { + function: &led_flash +}; + +/* proc */ + +static struct proc_dir_entry *diag, *leds; + +static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos); +static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data); + +static struct file_operations diag_proc_fops = { + read: diag_proc_read, + write: diag_proc_write +}; + +static struct prochandler_t proc_model = { .type = PROC_MODEL }; +static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK }; + +/* TODO: export existing sb_irq instead */ +static int sb_irq(void *sbh) +{ + uint idx; + void *regs; + sbconfig_t *sb; + uint32 flag, sbipsflag; + uint irq = 0; + + regs = sb_coreregs(sbh); + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + flag = (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK); + + idx = sb_coreidx(sbh); + + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) || + (regs = sb_setcore(sbh, SB_MIPS33, 0))) { + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + + /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ + sbipsflag = R_REG(&sb->sbipsflag); + for (irq = 1; irq <= 4; irq++, sbipsflag >>= 8) { + if ((sbipsflag & 0x3f) == flag) + break; + } + if (irq == 5) + irq = 0; + } + + sb_setcoreidx(sbh, idx); + + return irq; +} -- 2.30.2